package com.letv.core.network.volley;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;

import android.text.TextUtils;

import com.letv.core.network.volley.VolleyResponse.ResponseSupplier;
import com.letv.core.network.volley.exception.NetworkException;
import com.letv.core.network.volley.exception.VolleyException;
import com.letv.core.network.volley.listener.HttpStack;
import com.letv.core.network.volley.listener.Network;
import com.letv.core.network.volley.toolbox.ByteArrayPool;

/**
 * 执行http请求
 * 
 * @author zhuqiao
 * 
 */
public class BasicNetwork implements Network {
    private static int DEFAULT_POOL_SIZE = 4096;

    protected final HttpStack mHttpStack;

    protected final ByteArrayPool mPool;

    public BasicNetwork(HttpStack httpStack) {
        // 如果一个池没有通过，将建立一个小的默认缓存池，这样会给我们带来很大的益处，不需要耗费很多内存
        this(httpStack, new ByteArrayPool(DEFAULT_POOL_SIZE));
    }

    public BasicNetwork(HttpStack httpStack, ByteArrayPool pool) {
        mHttpStack = httpStack;
        mPool = pool;
    }

    @Override
    public VolleyResponse performRequest(VolleyRequest<?> request) throws VolleyException {
        if (request == null) {
            return new VolleyResponse(ResponseSupplier.NETWORK);
        }
        while (true) {
            try {
                HttpResponse httpResponse = null;
                try {
                    httpResponse = mHttpStack.performRequest(request);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new NetworkException();
                }

                if (httpResponse == null) {
                    throw new NetworkException();
                }

                StatusLine statusLine = httpResponse.getStatusLine();
                int statusCode = statusLine.getStatusCode();
                request.mNetWorkDataHull.addErrorInfo(1, statusCode + "");
                if (statusCode < 200 || statusCode > 299) {
                    throw new IOException();
                }

                if (mHttpStack instanceof HurlFileStack) {
                    return new VolleyResponse(statusLine.getReasonPhrase(), ResponseSupplier.NETWORK);
                }

                HttpEntity entity = httpResponse.getEntity();

                if (entity != null) {
                    String responseContents = entityToBytes(entity, request);
                    if (!TextUtils.isEmpty(responseContents)) {
                        return new VolleyResponse(responseContents, ResponseSupplier.NETWORK);
                    }
                }

                throw new IOException();
            } catch (IOException e) {
                e.printStackTrace();
                retry(request);
            } catch (NetworkException e) {
                e.printStackTrace();
                retry(request);
            }
        }
    }

    public void retry(VolleyRequest<?> request) throws VolleyException {
        if (request.getRetryPolicy() == null || !request.getRetryPolicy().retry()) {
            throw new VolleyException(VolleyException.CONNECT_FAIL);
        }
    }

    private String entityToBytes(HttpEntity entity, VolleyRequest<?> request) {
        InputStream is = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            is = entity.getContent();
            byte[] buff = new byte[1024];
            int readed = -1;
            while ((readed = is.read(buff)) != -1) {
                baos.write(buff, 0, readed);
            }
            byte[] result = baos.toByteArray();
            if (result == null)
                return null;

            return new String(result);
        } catch (Exception e) {
        } finally {
            try {
                if (is != null)
                    is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (baos != null)
                    baos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return null;
    }
}
